package cate.game.activity.limitshop;

import cate.common.table.activity.base.ShopActivityBaseRow;
import cate.common.table.activity.newlimitshop.core.NewLimitShopConditionBaseRow;
import cate.common.table.activity.newlimitshop.core.NewLimitShopConditionItemRow;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDOperation;
import cate.common.table.pay.PayItemRow;
import cate.common.util.GameResult;
import cate.common.util.TimeTool;
import cate.game.activity.limitshop.msg.LimitShopNewCondInfoResp;
import cate.game.role.Role;
import cate.game.role.task.TaskGroup;
import cate.game.role.task.TaskItem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class ConditionalLimitShopActivity extends LimitShopActivity {
    @NoteField("重置天数")
    public int resetDay;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (resetDay == 0) {
            resetDay = 1;
        }
    }

    @Override
    public void onEnter() {
        super.onEnter();
        excelCheck();
    }

    @Override
    public void excelCheck() {
        super.excelCheck();
        List<Integer> taskIds = getSelfConfigs().values().stream()
                .mapToInt(row -> row.taskId)
                .filter(taskId -> taskId > 0).boxed()
                .collect(Collectors.toList());
        TaskGroup taskGroup = role.getTask().getGroup(funcId());
        taskGroup.addItemListNoRepeat(taskIds);
    }

    @Override
    public void noticeUpdate() {
        role.sendNow(new LimitShopNewCondInfoResp(calcResetTime(), this));
    }

    /**
     * 计算重置时间
     */
    private long calcResetTime() {
        NewLimitShopConditionBaseRow config = getBaseConfig();
        if (config == null) {
            return endTime();
        }
        long nowTime = game().time.now();
        int day = getCurrentDay();
        if (config.resetType == 0) {
            return endTime();
        } else if (config.resetType == 1) {
            // 每日重置
            return TimeTool.getZeroTimeStamp(nowTime) + TimeTool.TimeCons.DAY;
        } else if (config.resetType == 2) {
            // 每周重置以7天为单位
            int next = (((day - 1) / 7) + 1) * 7;
            return Math.min(TimeTool.getZeroTimeStamp(startTime()) + next * TimeTool.TimeCons.DAY, endTime());
        } else if (config.resetType == 3) {
            // 每月重置以30天为单位
            int next = (((day - 1) / 30) + 1) * 30;
            return Math.min(TimeTool.getZeroTimeStamp(startTime()) + next * TimeTool.TimeCons.DAY, endTime());
        }
        return endTime();
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        NewLimitShopConditionBaseRow config = getBaseConfig();
        if (config == null) {
            return;
        }
        int day = getCurrentDay();
        if (config.resetType == 1) {
            // 每日重置
            reset();
        } else if (config.resetType == 2) {
            // 每周重置以7天为单位
            if (day - resetDay >= 7) {
                reset();
                resetDay = ((day - 1) / 7) * 7 + 1;
            }
        } else if (config.resetType == 3) {
            // 每月重置以30天为单位
            if (day - resetDay >= 30) {
                reset();
                resetDay = ((day - 1) / 30) * 30 + 1;
            }
        }
        noticeUpdate();
    }

    /**
     * 重置数据
     */
    private void reset() {
        buyRecords.entrySet().forEach(entry -> entry.setValue(0));
    }

    @Override
    public void onWeekSpan(boolean silence) {
        // 周重置改啦
    }

    @Override
    public void onMonthSpan(boolean silence) {
        // 月重置改啦
    }

    @Override
    public void onRoleEnd() {
        super.onRoleEnd();
        resetDay = 1;
    }


    /**
     * 获取活动基础配置
     */
    @JsonIgnore
    private NewLimitShopConditionBaseRow getBaseConfig() {
        switch (funcId()) {
            case GDFunc.ACT_COND_SHOP_ROOKIE:
                return role.getGame().table.limitShopNew.rookie_base.get(configTid());
            case GDFunc.ACT_DAILY_SHOP_NEW_TWO:
            case GDFunc.ACT_COND_SHOP_WEEK:
            case GDFunc.ACT_COND_SHOP_MONTH:
                return role.getGame().table.limitShopNew.period_base.get(configTid());
            default:
                return null;
        }
    }

    /**
     * 获取活动特定物品配置
     *
     * @param tid 配置ID
     */
    @JsonIgnore
    private NewLimitShopConditionItemRow getSelfConfig(int tid) {
        switch (funcId()) {
            case GDFunc.ACT_COND_SHOP_ROOKIE:
                return role.getGame().table.limitShopNew.rookie_item.get(tid);
            case GDFunc.ACT_DAILY_SHOP_NEW_TWO:
            case GDFunc.ACT_COND_SHOP_WEEK:
            case GDFunc.ACT_COND_SHOP_MONTH:
                return role.getGame().table.limitShopNew.period_item.get(tid);
            default:
                return null;
        }
    }

    @Override
    @JsonIgnore
    protected ShopActivityBaseRow getConfig(int tid) {
        return getSelfConfig(tid);
    }

    /**
     * 获取特定配置集合
     */
    @JsonIgnore
    protected Map<Integer, NewLimitShopConditionItemRow> getSelfConfigs() {
        Map<Integer, NewLimitShopConditionItemRow> retMap = new HashMap<>();
        switch (funcId()) {
            case GDFunc.ACT_COND_SHOP_ROOKIE: {
                NewLimitShopConditionBaseRow config = getBaseConfig();
                if (config != null) {
                    retMap.putAll(role.getGame().table.limitShopNew.rookie_item.getItems(config.group)
                            .stream().collect(Collectors.toMap(e -> e.id, v -> v)));
                }
            }
            break;
            case GDFunc.ACT_DAILY_SHOP_NEW_TWO:
            case GDFunc.ACT_COND_SHOP_WEEK:
            case GDFunc.ACT_COND_SHOP_MONTH: {
                NewLimitShopConditionBaseRow config = getBaseConfig();
                if (config != null) {
                    retMap.putAll(role.getGame().table.limitShopNew.period_item.getItems(config.group)
                            .stream().collect(Collectors.toMap(e -> e.id, v -> v)));
                }
            }
            break;
        }
        return retMap;
    }

    @Override
    @JsonIgnore
    protected Map<Integer, ShopActivityBaseRow> getConfigs() {
        return new HashMap<>(getSelfConfigs());
    }

    @Override
    public GameResult<Void> allowPay(PayItemRow pir) {
        if (!preCheck(pir.funcSubId)) {
            return new GameResult<Void>().fail("未达成购买条件!");
        }
        return super.allowPay(pir);
    }

    @Override
    protected int getGDOperation() {
        switch (funcId()) {
            case GDFunc.ACT_COND_SHOP_ROOKIE:
                return GDOperation.ACT_COND_SHOP_ROOKIE;
            case GDFunc.ACT_COND_SHOP_WEEK:
                return GDOperation.ACT_COND_SHOP_WEEK;
            case GDFunc.ACT_COND_SHOP_MONTH:
                return GDOperation.ACT_COND_SHOP_MONTH;
            case GDFunc.ACT_DAILY_SHOP_NEW_TWO:
                return GDOperation.ACT_DAILY_SHOP_NEW_TWO;
            default:
                return super.getGDOperation();
        }
    }

    @Override
    public GameResult<LimitShopActivity> buyItem(int tid, int num) {
        if (!preCheck(tid)) {
            return new GameResult<LimitShopActivity>().fail("未达成购买条件!");
        }
        return super.buyItem(tid, num);
    }

    /**
     * 提前检测条件
     *
     * @param tid 配置ID
     */
    private boolean preCheck(int tid) {
        NewLimitShopConditionItemRow config = getSelfConfig(tid);
        if (config == null) {
            return false;
        }
        if (config.taskId != 0) {
            TaskGroup taskGroup = role.getTask().getGroup(funcId());
            TaskItem task = taskGroup.getItem(config.taskId);
            return task != null && task.done;
        }
        return true;
    }
}
